<template>
	<org-tree
		:bordered="bordered"
		:direction="direction"
		v-for="child in store.tree"
		:node="child"
		:key="child.id"
	/>
	<ContextMenu ref="contextMenuRef" @emitMenu="onEmitMenu" />
</template>

<script setup lang="ts">
import ContextMenu from "./context-menu/index.tsx";
import { ref, computed, reactive, provide } from "vue";
import Tree from "./tree";
import orgTreeProps from "./org-tree";
import { addUnit, splitUnit } from "./utils/org-tree";

const props = defineProps(orgTreeProps);

const store = reactive(
	new Tree({
		data: props.treeData
	})
);

const contextMenuRef = ref<InstanceType<typeof ContextMenu>>();
const internalData = reactive({
	showMenu(option: Record<string, any>) {
		contextMenuRef.value.showModal(option);
	}
});
provide("context", internalData);

const onEmitMenu = ({
	command,
	currentNode
}: {
	command: string;
	currentNode: Record<string, any>;
}) => {
	switch (command) {
		case "add":
			store.addChild(currentNode);
			break;
		case "edit":
			currentNode.focus = true;
			break;
		case "delete":
			store.removeChild(currentNode);
			break;
		default:
			return false;
	}
	currentNode.expanded = true;
};

// 按钮几何属性
const buttonAttribute = computed(() => {
	const radius = props.button ? (props.button.radius ? props.button.radius : "20px") : "20px";
	return {
		w: addUnit(radius),
		h: addUnit(radius),
		ml:
			props.direction === "vertical"
				? "-" + addUnit(splitUnit(radius) / 2)
				: addUnit(splitUnit(radius) / 2),
		mt:
			props.direction === "vertical"
				? addUnit(splitUnit(radius) / 2)
				: "-" + addUnit(splitUnit(radius) / 2),
		gap: addUnit(radius)
	};
});
</script>

<style lang="scss">
.label--boxshadow {
	box-shadow: 0 1px 10px rgba(31, 35, 41, 0.08);
}
.label--bordered {
	border: 1px solid rgb(229, 231, 235);
}

// 水平
.horizontal {
	display: flex;
	align-items: center;
	.org-chart-node {
		padding: 0px 5px 0 v-bind("buttonAttribute.gap");
		display: flex;
		align-items: center;
	}
	.org-chart-label {
		position: relative;
	}

	.org-node-btn {
		position: absolute;
		left: 100%;
		top: 50%;
		width: v-bind("buttonAttribute.w");
		height: v-bind("buttonAttribute.h");
		z-index: 10;
		margin-top: v-bind("buttonAttribute.mt");
		margin-left: v-bind("buttonAttribute.ml");
		background-color: #fff;
		border: 1px solid rgb(229, 231, 235);
		border-radius: 50%;
		cursor: pointer;
		transition: box-shadow 0.2s;
		&::before {
			content: "";
			position: absolute;
			width: 70%;
			height: 2px;
			top: 0;
			left: 0;
			bottom: 0;
			right: 0;
			margin: auto;
			background-color: rgb(229, 231, 235);
		}
		&:hover {
			box-shadow: 0 0 12px rgba(0, 0, 0, 0.12);
		}
	}
	.org-node-btn--expand {
		&::after {
			content: "";
			position: absolute;
			width: 2px;
			height: 70%;
			top: 0;
			left: 0;
			bottom: 0;
			right: 0;
			margin: auto;
			background-color: rgb(229, 231, 235);
		}
	}

	.org-chart-node-label-inner {
		padding: 10px;
		display: inline-block; // 配合 marigin 垂直居中
		margin: 10px 0;
		border-radius: 3px;
		user-select: none;
		.input {
			min-width: 100px;
			field-sizing: content;
		}
	}

	.org-chart-node-children {
		padding-left: v-bind("buttonAttribute.gap");
		position: relative;
		.org-chart-node {
			position: relative;
			&::before {
				content: "";
				width: v-bind("buttonAttribute.w");
				height: 50%;
				position: absolute;
				left: 0;
				top: 0;
				border-left: 1px solid rgb(229, 231, 235);
			}
			&::after {
				content: "";
				width: v-bind("buttonAttribute.w");
				height: 50%;
				position: absolute;
				left: 0;
				bottom: 0;
				border-top: 1px solid rgb(229, 231, 235);
				border-left: 1px solid rgb(229, 231, 235);
			}
		}

		& > :last-child::after {
			border-left: none;
		}
		& > :first-child::before {
			border-left: none;
		}
	}
	.children-line--before {
		&::before {
			content: "";
			position: absolute;
			left: 0;
			top: 50%;
			border-top: 1px solid rgb(229, 231, 235);
			width: 20px;
			height: 10px;
		}
	}

	.label-line--after {
		&::after {
			content: "";
			position: absolute;
			left: 100%;
			top: 0%;
			border-bottom: 1px solid rgb(229, 231, 235);
			width: 10px;
			height: 50%;
		}
	}
}

// 垂直
.vertical {
	.org-chart-node-children {
		display: flex;
		padding-top: v-bind("buttonAttribute.gap");
		position: relative;
		.org-chart-node {
			position: relative;
			&::before {
				content: "";
				width: 50%;
				height: v-bind("buttonAttribute.h");
				position: absolute;
				left: 0;
				top: 0;
				border-right: 1px solid rgb(229, 231, 235);
				border-top: 1px solid rgb(229, 231, 235);
			}
			&::after {
				content: "";
				width: 50%;
				height: v-bind("buttonAttribute.h");
				position: absolute;
				left: 50%;
				top: 0;
				border-top: 1px solid rgb(229, 231, 235);
			}
		}
		& > :last-child::after {
			border-top: none;
		}
		& > :first-child::before {
			border-top: none;
		}
	}
	.org-chart-node {
		padding: v-bind("buttonAttribute.gap") 5px 0 5px;
		margin: 0 auto;
	}
	.org-chart-label {
		position: relative;
		display: flex;
		justify-content: center;
	}

	.org-node-btn {
		position: absolute;
		left: 50%;
		top: 100%;
		width: v-bind("buttonAttribute.w");
		height: v-bind("buttonAttribute.h");
		z-index: 10;
		margin-left: v-bind("buttonAttribute.ml");
		margin-top: v-bind("buttonAttribute.mt");
		background-color: #fff;
		border: 1px solid rgb(229, 231, 235);
		border-radius: 50%;
		cursor: pointer;
		transition: box-shadow 0.2s;
		&::before {
			content: "";
			position: absolute;
			width: 70%;
			height: 2px;
			top: 0;
			left: 0;
			bottom: 0;
			right: 0;
			margin: auto;
			background-color: rgb(229, 231, 235);
		}
		&:hover {
			box-shadow: 0 0 12px rgba(0, 0, 0, 0.12);
		}
	}
	.org-node-btn--expand {
		&::after {
			content: "";
			position: absolute;
			width: 2px;
			height: 70%;
			top: 0;
			left: 0;
			bottom: 0;
			right: 0;
			margin: auto;
			background-color: rgb(229, 231, 235);
		}
	}

	.org-chart-node-label-inner {
		padding: 10px;
		display: inline-block; // 配合 marigin 垂直居中
		border-radius: 3px;
		user-select: none;
	}

	.label-line--before {
		&::after {
			background-color: rgb(229, 231, 235);
			content: "";
			position: absolute;
			bottom: -50%;
			left: 50%;
			height: 50%;
			width: 1px;
		}
	}
}
</style>
